package engine.controller;

import java.util.ArrayList;
import java.awt.Component;
import engine.model.EngineProperties;
import engine.model.OutsideEnvironmentException;
import engine.model.PhysicsObject;
import engine.model.EndLevelException;
import engine.model.PhysicsEngine;

public class PhysicsControl {
	private PhysicsEngine engine;
	
	public PhysicsControl(Component ui, EngineProperties settings) {
		engine = new PhysicsEngine(ui.getWidth(), ui.getHeight(), settings);
		ui.addKeyListener(engine);
		
	}
	
	public PhysicsControl(Component ui, EngineProperties settings, int env_x, int env_y) {
		engine = new PhysicsEngine(env_x, env_y, settings);
		ui.addKeyListener(engine);
	}
	
	/*
	 * pre-cond: PhysicsEngine must not be running.
	 * post-cond: Objects in the arraylist objs are added to the environment inside of PhysicsEngine
	 * 		one at a time. If an object with the same position already exists in the environment, the
	 * 		new object will replace the old. If an object outside the bounds of the environment exists
	 * 		in the arraylist objs, all objects before it are added to the environment and the
	 * 		OutsideEnvironmentException is thrown.
	 */
	public void loadObjects(ArrayList<PhysicsObject> objs) throws OutsideEnvironmentException {
		engine.addObjects(objs);
	}
	
	/*
	 * pre-cond: none
	 * post-cond: method returns all objects present in PhysicsEngine's environment inside
	 * 		an ArrayList.
	 */
	public ArrayList<PhysicsObject> getObjects() {
		return engine.getObjects();
	}
	
	/*
	 * pre-cond: PhysicsEngine must not be already running.
	 * post-cond: PhysicsEngine begins simulating physical effects on the objects in the
	 * 		environment, repeatedly calling tick() on all objects in the environment until
	 * 		an EndLevel exception occurs or pauseLevel() is called.
	 */
	public void startLevel() throws EndLevelException {
		engine.start();
	}
	
	/*
	 * pre-cond: startLevel() has been called and PhysicsEngine is running.
	 * post-cond: PhysicsEngine pauses execution.
	 */
	public void pauseLevel() {
		synchronized(engine) {
			engine.pleaseWait = true;
		}
	}
	
	/*
	 * pre-cond: pauseLevel() has been called.
	 * post-cond: PhysicsEngine resumes execution.
	 */
	public void resumeLevel() {
		synchronized(engine) {
			engine.pleaseWait = false;
			engine.notify();
		}
	}
}